package repository

import (
	"context"
	"errors"
	"time"

	"github.com/example/video_backend/internal/model"
	"gorm.io/gorm"
)

// ConversationRepository 对话仓库接口
type ConversationRepository interface {
	Create(ctx context.Context, conversation *model.Conversation) error
	GetByID(ctx context.Context, id uint) (*model.Conversation, error)
	GetUserConversations(ctx context.Context, userID uint, page, pageSize int) ([]*model.Conversation, int64, error)
	Update(ctx context.Context, conversation *model.Conversation) error
	Delete(ctx context.Context, id uint) error
	UpdateLastActive(ctx context.Context, id uint) error
}

// MessageRepository 消息仓库接口
type MessageRepository interface {
	Create(ctx context.Context, message *model.Message) error
	GetConversationMessages(ctx context.Context, conversationID uint, page, pageSize int) ([]*model.Message, error)
	DeleteConversationMessages(ctx context.Context, conversationID uint) error
}

// conversationRepository 实现ConversationRepository接口
type conversationRepository struct {
	DB *gorm.DB
}

// messageRepository 实现MessageRepository接口
type messageRepository struct {
	DB *gorm.DB
}

// NewConversationRepository 创建对话仓库实例
func NewConversationRepository(db *gorm.DB) ConversationRepository {
	return &conversationRepository{DB: db}
}

// NewMessageRepository 创建消息仓库实例
func NewMessageRepository(db *gorm.DB) MessageRepository {
	return &messageRepository{DB: db}
}

// Create 创建对话
func (r *conversationRepository) Create(ctx context.Context, conversation *model.Conversation) error {
	conversation.LastActive = time.Now()
	return r.DB.WithContext(ctx).Create(conversation).Error
}

// GetByID 获取对话详情
func (r *conversationRepository) GetByID(ctx context.Context, id uint) (*model.Conversation, error) {
	var conversation model.Conversation
	err := r.DB.WithContext(ctx).First(&conversation, id).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &conversation, nil
}

// GetUserConversations 获取用户的对话列表
func (r *conversationRepository) GetUserConversations(ctx context.Context, userID uint, page, pageSize int) ([]*model.Conversation, int64, error) {
	var conversations []*model.Conversation
	var total int64

	// 计算偏移量
	offset := (page - 1) * pageSize

	// 构建查询
	query := r.DB.WithContext(ctx).Where("user_id = ?", userID).Order("last_active DESC")

	// 查询总数
	query.Model(&model.Conversation{}).Count(&total)

	// 查询分页数据
	err := query.Offset(offset).Limit(pageSize).Find(&conversations).Error
	if err != nil {
		return nil, 0, err
	}

	return conversations, total, nil
}

// Update 更新对话
func (r *conversationRepository) Update(ctx context.Context, conversation *model.Conversation) error {
	conversation.UpdatedAt = time.Now()
	conversation.LastActive = time.Now()
	return r.DB.WithContext(ctx).Save(conversation).Error
}

// Delete 删除对话
func (r *conversationRepository) Delete(ctx context.Context, id uint) error {
	return r.DB.WithContext(ctx).Delete(&model.Conversation{}, id).Error
}

// UpdateLastActive 更新对话的最后活跃时间
func (r *conversationRepository) UpdateLastActive(ctx context.Context, id uint) error {
	return r.DB.WithContext(ctx).Model(&model.Conversation{}).Where("id = ?", id).Update("last_active", time.Now()).Error
}

// Create 创建消息
func (r *messageRepository) Create(ctx context.Context, message *model.Message) error {
	return r.DB.WithContext(ctx).Create(message).Error
}

// GetConversationMessages 获取对话的消息列表
func (r *messageRepository) GetConversationMessages(ctx context.Context, conversationID uint, page, pageSize int) ([]*model.Message, error) {
	var messages []*model.Message

	// 计算偏移量
	offset := (page - 1) * pageSize

	// 查询分页数据
	err := r.DB.WithContext(ctx).Where("conversation_id = ?", conversationID).
		Offset(offset).Limit(pageSize).Order("created_at ASC").Find(&messages).Error

	return messages, err
}

// DeleteConversationMessages 删除对话的所有消息
func (r *messageRepository) DeleteConversationMessages(ctx context.Context, conversationID uint) error {
	return r.DB.WithContext(ctx).Where("conversation_id = ?", conversationID).Delete(&model.Message{}).Error
}